package com.xhtt.common.utils;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.xssf.usermodel.*;

import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 导出Excel
 */
public class ExportExcel<T> {

    /**
     * 导出模板
     *
     * @param sheetName sheets 名称
     * @param fileName  导出的文件名
     * @param headers   列头名
     * @param columns   字段名
     * @param result    数据集合
     * @param response  HttpServletResponse
     * @throws Exception
     */
    public void exportExcel(String fileName, String sheetName,
                            String[] headers, String[] columns, Collection<T> result,
                            HttpServletResponse response) throws Exception {
        //声明工作薄
        XSSFWorkbook workbook = new XSSFWorkbook();
        //创建sheet
        XSSFSheet sheet = workbook.createSheet(sheetName);
        //创建第0行，填充列头
        int index = 0;
        this.iterationHeaders(sheet, index, headers);
        //创建第1行，填充数据
        this.iterationData(sheet, index, columns, result);

        OutputStream out = response.getOutputStream();// 取得输出流
        response.reset();// 清空输出流
        response.setHeader("Content-disposition", "attachment; filename=" + new String(fileName.getBytes("GBK"), "8859_1") + ".xlsx");// 设定输出文件头
        response.setContentType("application/msexcel");// 定义输出类型
        workbook.write(out);
        out.flush();
        out.close();
    }


    /**
     * 遍历列头
     *
     * @param sheet
     * @param index
     * @param headers
     */
    private void iterationHeaders(XSSFSheet sheet, int index, String[] headers) {
        XSSFRow row = sheet.createRow(index);
        for (int i = 0; i < headers.length; i++) {
            sheet.setColumnWidth(i, 20 * 256);
            XSSFCell cell = row.createCell(i);
            XSSFRichTextString text = new XSSFRichTextString(headers[i]);
            cell.setCellValue(text);
        }
    }

    /**
     * 遍历数据
     *
     * @param sheet
     * @param index
     * @param columns
     * @param result
     * @throws Exception
     */
    private void iterationData(XSSFSheet sheet, int index, String[] columns, Collection<T> result) throws Exception {
        // 遍历集合数据，产生数据行
        if (result != null) {
            index++;
            XSSFRow row = null;
            for (T t : result) {
                row = sheet.createRow(index);
                index++;
                for (int i = 0; i < columns.length; i++) {
                    XSSFCell cell = row.createCell(i);
                    String fieldName = columns[i];
                    String getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
                    Object value;
                    if (t instanceof HashMap) {
                        HashMap<String, Object> m = (HashMap<String, Object>) t;
                        value = m.get(fieldName);
                    } else {
                        Class tCls = t.getClass();
                        Method getMethod = tCls.getMethod(getMethodName, new Class[]{});
                        // getMethod.getReturnType().isInstance(obj);
                        value = getMethod.invoke(t, new Object[]{});
                    }


                    this.conversionType(value, cell);
                }
            }
        }
    }

    /**
     * 数值转换
     *
     * @param value
     * @param cell
     */
    private void conversionType(Object value, XSSFCell cell) {
        String textValue = null;
        if (value == null) {
            textValue = "";
        } else if (value instanceof Date) {
            textValue = DateUtils.format((Date) value, DateUtils.DATE_TIME_PATTERN);
        } else if (value instanceof LocalDateTime) {
            textValue = ((LocalDateTime) value).format(DateUtils.dtfm);
        } else {
            //其它数据类型都当作字符串简单处理
            textValue = value.toString();
        }
        if (StringUtils.isNotEmpty(textValue)) {
            Pattern p = Pattern.compile("^//d+(//.//d+)?$");
            Matcher matcher = p.matcher(textValue);
            if (matcher.matches()) {
                //是数字当作double处理
                cell.setCellValue(Double.parseDouble(textValue));
            } else {
                XSSFRichTextString richString = new XSSFRichTextString(textValue);
                cell.setCellValue(richString);
            }
        }
    }

}
